package com.steinwurf.hdcjoinwifi;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.bundle.IBundleManager;
import ohos.event.commonevent.CommonEventManager;
import ohos.event.commonevent.CommonEventSubscribeInfo;
import ohos.event.commonevent.MatchingSkills;
import ohos.os.ProcessManager;
import ohos.rpc.RemoteException;
import ohos.utils.IntentConstants;
import ohos.wifi.WifiDevice;
import ohos.wifi.WifiDeviceConfig;
import ohos.wifi.WifiEvents;
import ohos.wifi.WifiSecurity;
import ohos.wifi.WifiScanInfo;

import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MainAbility extends Ability implements CheckSSIDBroadcastReceiver.SSIDFoundListener {
    private static final String TAG = "qinjinchuan_MainAbility";

    private static final String WEP_PASSWORD = "WEP";
    private static final String WPA_PASSWORD = "WPA";

    private static final String SSID = "ssid";
    private static final String PASSWORD_TYPE = "password_type";
    private static final String PASSWORD = "password";

    private static final String PROXY_HOST = "proxy_host";
    private static final String PROXY_PORT = "proxy_port";
    private static final String PROXY_BYPASS = "proxy_bypass";
    private static final String PROXY_PAC_URI = "proxy_pac_uri";

    private static final String CLEAR_DEVICE_ADMIN = "clear_device_admin";

    String mSSID;
    String mPassword;
    String mPasswordType;
//    ProxyInfo mProxyInfo;


    CheckSSIDBroadcastReceiver broadcastReceiver;
    WifiDevice mWifiDevice = WifiDevice.getInstance(this);

    Thread mThread;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        attempJoinWifi();
    }

    private void printUsage() {
        Logger.getLogger(TAG).log(Level.INFO, "No datastring provided. use the following hdc command:");
        Logger.getLogger(TAG).log(Level.INFO,
                "hdc shell am start" +
                        " -n com.steinwurf.hdcjoinwifi/.MainAbility " +
                        "-e ssid SSID " +
                        "-e password_type [WEP|WPA] " +
                        "-e password PASSWORD " +
                        "\nOptional proxy args:\n" +
                        "    -e proxy_host HOSTNAME " +
                        "-e proxy_port PORT " +
                        "[-e proxy_bypass COMMA,SEPARATED,LIST]\n" +
                        "    OR\n" +
                        "    -e proxy_pac_uri http://my.proxy.config/url\n" +
                        "If app was granted device owner using dpm, you can unset it with:\n" +
                        "    -e clear_device_admin true");
        new ToastDialog(getContext()).setText("This application is meant to be used with HDC").show();
        terminateAbility();
    }

    private void registerEventSubsciber() {
        MatchingSkills match = new MatchingSkills();
        match.addEvent(WifiEvents.EVENT_ACTIVE_STATE);
        match.addEvent(WifiEvents.EVENT_CONN_STATE);
        CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(match);
        subscribeInfo.setPriority(100);
        CheckSSIDBroadcastReceiver subscriber = new CheckSSIDBroadcastReceiver(subscribeInfo, mWifiDevice, mSSID);
        subscriber.setSSIDFoundListener(this);
        try {
            CommonEventManager.subscribeCommonEvent(subscriber);
        } catch (RemoteException e) {
            Logger.getLogger(TAG).log(Level.WARNING, "subscribe in wifi events failed!");
        }
    }

    private void attempJoinWifi() {

        mSSID = "test";
        mPasswordType = "WPA";
        mPassword = "12345678";


        String proxyHost = getIntent().getStringParam(PROXY_HOST);
        String proxyPort = getIntent().getStringParam(PROXY_PORT);
        String proxyBypass = getIntent().getStringParam(PROXY_BYPASS);
        String proxyPacUri = getIntent().getStringParam(PROXY_PAC_URI);

        // Validate
        if ((mSSID == null) || // SSID REQUIRED
                (mPasswordType != null && mPassword == null) || // PASSWORD REQUIRED IF PASSWORD TYPE GIVEN
                (mPassword != null && mPasswordType == null) || // PASSWORD TYPE REQUIRED IF PASSWORD GIVEN
                (mPasswordType != null && !mPasswordType.equals(WPA_PASSWORD) && !mPasswordType.equals(WEP_PASSWORD))) { // PASSWORD TYPE MUST BE NULL OR WPA OR WEP
            printUsage();
            return;
        }

        Logger.getLogger(TAG).log(Level.INFO, "Trying to join:");
        Logger.getLogger(TAG).log(Level.INFO, "SSID: " + mSSID);
        if (mPasswordType != null && mPassword != null) {
            Logger.getLogger(TAG).log(Level.INFO, "Password Type: " + mPasswordType);
            Logger.getLogger(TAG).log(Level.INFO, "Password: " + mPassword);
        }

        // Setup layout
        DirectionalLayout layout = new DirectionalLayout(this);
        setUIContent(layout);
        layout.setAlignment(LayoutAlignment.CENTER);
        layout.setOrientation(Component.VERTICAL);
        ComponentContainer.LayoutConfig config = new ComponentContainer.LayoutConfig();
        config.width = ComponentContainer.LayoutConfig.MATCH_CONTENT;
        config.height = ComponentContainer.LayoutConfig.MATCH_CONTENT;
        layout.setLayoutConfig(config);
        Text textView = new Text(this);
        textView.setText(ResourceTable.String_trying_to_connect_to);
        textView.setPadding(300,0,50,0);
        textView.setTextSize(50);
        layout.addComponent(textView, config);
        Text SSIDtextview = new Text(this);
        SSIDtextview.setText(mSSID);
        SSIDtextview.setTextSize(50);
        layout.addComponent(SSIDtextview, config);

        // Setup broadcast receiver
        registerEventSubsciber();

        if (!mWifiDevice.isWifiActive()) {
            Logger.getLogger(TAG).log(Level.INFO,"wifi is inactive");
            //To-do:how to enabled wifi on openharmony 
            Intent intent = new Intent();
            intent.setAction(IntentConstants.ACTION_WIRELESS_SETTINGS);
            intent.addFlags(Intent.FLAG_ABILITY_NEW_MISSION);
            startAbility(intent);
        } else {
            wifiEnabled();
        }
    }

    @Override
    public void SSIDFound() {
        Logger.getLogger(TAG).log(Level.INFO,"Device Connected to " + mSSID);
        if (mThread != null) {
            mThread.interrupt();
            try {
                mThread.join();
            } catch (InterruptedException e) {
                Logger.getLogger(TAG).log(Level.INFO,"Hit exception", e);
            }
        }
        //terminateAbility();
    }

    @Override
    public void wifiEnabled() {
        if (mThread != null) {
            return;
        }

        WifiDeviceConfig wfc = null;
        boolean success = false;

        if (wfc == null) {
            // Wifi configuration didn't exist for this SSID, create it.
            wfc = new WifiDeviceConfig();
            updateWifiConfiguration(wfc);
            success = mWifiDevice.addUntrustedConfig(wfc);
        } else if (permittedToUpdate(wfc)) {
            // Wifi configuration already exists, update if we can
            updateWifiConfiguration(wfc);
        }

        if (!success) {
            Logger.getLogger(TAG).log(Level.INFO,"Invalid wifi network (ensure this SSID exists, auth method and password are correct, etc.)");
            //terminateAbility();
            return;
        }
    }

    private boolean permittedToUpdate(WifiDeviceConfig wfc) {
        Field field;
        int creatorUid;

        try {
            field = wfc.getClass().getDeclaredField("creatorUid");
            creatorUid = field.getInt(wfc);
        } catch (ReflectiveOperationException e) {
            Logger.getLogger(TAG).log(Level.INFO,"Hit exception", e);
            //To-do
            creatorUid = ProcessManager.getUid();
        }
        try {
            //ohos.permission.GET_BUNDLE_INFO
            IBundleManager bunldeManager = getBundleManager();
            if (creatorUid == bunldeManager.getBundleInfo("com.steinwurf.hdcjoinwifi", 0).getUid()) {
                Logger.getLogger(TAG).log(Level.INFO, "App is permitted to modify this wifi configuration");
                return true;
            }
        } catch (RemoteException | SecurityException e) {
            Logger.getLogger(TAG).log(Level.INFO, "getBunldeInfo exception for : " + e);
        }
        // Since app doesn't have proper permissions, we will join the existing Wifi network as configured
        Logger.getLogger(TAG).log(Level.INFO,"App does not have admin access, unable to modify a wifi network created by another app");
        return false;
    }

    private void updateWifiConfiguration(WifiDeviceConfig wfc) {
        wfc.setSsid(mSSID);
        if (mPasswordType == null) { // no password
            wfc.setSecurityType(WifiSecurity.OPEN);
            wfc.setRestricted(false);
            wfc.setHiddenSsid(false);
        } else if (mPasswordType.equals(WEP_PASSWORD)) { // WEP
            wfc.setSecurityType(WifiSecurity.WEP);
            wfc.setRestricted(false);
            wfc.setHiddenSsid(false);
            // if hex string
            // wfc.wepKeys[0] = password;

            wfc.setPreSharedKey(mPassword);
        } else if (mPasswordType.equals(WPA_PASSWORD)) { // WPA(2)
            wfc.setSecurityType(WifiSecurity.PSK);
            wfc.setRestricted(false);
            wfc.setHiddenSsid(false);
            wfc.setPreSharedKey(mPassword);
        }
    }

    //To-do:WifiManager.getConfiguredNetworks()
    private WifiScanInfo getExistingWifiConfiguration() {
        for ( WifiScanInfo i : mWifiDevice.getScanInfoList()) {
            if (i.getSsid() != null && i.getSsid().equals("\"".concat(mSSID).concat("\""))) {
                Logger.getLogger(TAG).log(Level.INFO, "wifi network already exists.");
                return i;
            }
        }
        return null;
    }
}
